package com.neuedu.security.security;

import com.neuedu.security.entity.SysUser;
import com.neuedu.security.utils.JWTUtils;
import org.junit.jupiter.api.Order;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.WebSecurityConfigurer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {


    @Autowired
    PasswordEncoder passwordEncoder;

    @Autowired
    SecurityAuthenticationEntryPoint securityAuthenticationEntryPoint;


    @Autowired
    SecurityUserDetailsService userDetailsService;

    @Bean
    PasswordEncoder  passwordEncoder(){
        return new BCryptPasswordEncoder();
    }


//    @Override
//    public void configure(WebSecurity web) throws Exception {
//        super.configure(web);
//
//    }




    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.csrf().disable();

        //不需要额外的创建SESSION
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);


        //表单信息处理
        http.formLogin()
                //定制登录页面
//                .loginPage("/login.html")
//                //表单控件的参数名字
//                .usernameParameter("uname")
//                .passwordParameter("")
        .permitAll();// 表单的相关请求 不需要授权






//        http.authorizeRequests().anyRequest().

        //给某一个路径添加 需要有  admin的角色才能访问
        http.authorizeRequests()
                .mvcMatchers("/index")
//                .hasAuthority("system:user:query")
                .hasRole("admin");

        //这些路径是不需要 认证、不需要授权
        http.authorizeRequests().mvcMatchers("/doc.html","/**/*.js" ,"/**/*.js","/login").permitAll();


        http.authorizeRequests().antMatchers(HttpMethod.OPTIONS).permitAll();
        http.cors().configurationSource(corsSource());

        //除了上面之外的 都需要认证(登录才能访问)
        http.authorizeRequests().anyRequest().authenticated();




        //异常的处理
        http.exceptionHandling()
//                    自定义页面
//                .accessDeniedPage("/my403.html")
                //自定义Handler
//                .accessDeniedHandler()
                //针对异常自定义的代码
                .authenticationEntryPoint(securityAuthenticationEntryPoint);



        http.addFilterBefore(new OncePerRequestFilter(){
            @Override
            protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

                //从request中的Header取出Token

//                String pass = request.getParameter("pass");
//
//                if("true".equals(pass)){
//                    //解析token字符串
//                    UserDetails userDetail = userDetailsService.loadUserByUsername("admin");
//                    UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(userDetail , "" ,userDetail.getAuthorities());
//                    authRequest.setDetails(userDetail);
//                    //在上下文（当前线程）中添加 认证的身份
//                    //设置后，后续所有的 授权
//                    SecurityContextHolder.getContext().setAuthentication(authRequest);
//                }


                String token = request.getHeader("Authorization");

                if(token != null && !"".equals(token) && token.length()>0){
                    try {
                        SysUser user = JWTUtils.decode(token);

                        //解析token字符串
                        UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(user.getUserName(), user.getPassword());
                        authRequest.setDetails(userDetailsService.loadUserByUsername(user.getUserName()));
                        //在上下文（当前线程）中添加 认证的身份
                        //设置后，后续所有的 授权
                        SecurityContextHolder.getContext().setAuthentication(authRequest);

                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }

                //放行请求
                filterChain.doFilter(request,response);


            }
        } , UsernamePasswordAuthenticationFilter.class);

    }




    /**
     * 跨域配置
     */
    CorsConfigurationSource corsSource(){
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        // 设置访问源地址
        config.addAllowedOriginPattern("*");
        // 设置访问源请求头
        config.addAllowedHeader("*");
        // 设置访问源请求方法
        config.addAllowedMethod("*");
        // 有效期 1800秒
        config.setMaxAge(1800L);
        // 添加映射路径，拦截一切请求
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);
        return source;
    }



//    @Override
//    protected UserDetailsService userDetailsService() {
//        return new SecurityUserDetailsService();
//    }

//    @Override
//    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//        String rawPassword = "123456";
//        auth.inMemoryAuthentication().withUser("liubei").password(passwordEncoder.encode(rawPassword)).roles("admin");
//    }


    public static void main(String[] args) {

        //原始密码加密
        String encode = new BCryptPasswordEncoder().encode("123456");
        System.out.println("encode = " + encode);



        //验证密码是否正确
        String encodePass = "$2a$10$RkOu41THHLHw/O/oXcOnf..5Y2pkQmJfk0PLo8gTNCpLI660.7FYu";
        boolean matches = new BCryptPasswordEncoder().matches("1234561", encodePass);
        System.out.println("matches = " + matches);
    }

}
